The venerable Western Hemlock has been in decline in the Puget Lowlands since 2015. Researchers initially believed this novel mortality was caused by Rhizoctonia butini, a fungus in the order Cantharellales. This hypothesis has since fallen out of favor (Jared LeBoldus, OSU Corvallis, personal communication). No replacement theory has arisen.

Scientists and citizens oftne suggest that the mortality is due simply to old age - normal senescence - or to changes in weather patterns related to climate change.

As with the sword fern blight, Seward Park’s old-growth urban forest presents an opportunity to study the hemlock decline.

The 120 acre forest forest has approximately 1000 hemlocks of all ages. Healthy hemlocks are common, newborn seedlings to four foot diameter 250 year odl giants. Diseased, dead and dying hemlocks are common also, and appear to be concentrated in the northernmost forest.

Informal observation led forest steward Paul Shannon to suppose that two small (hectare-sized) hemlock-rich sites at Seward may have roughly equivalent age and density distributions, yet radically different health profiles. These contrasting sites may provide an opportunity to study contrasting health and disease, and perhaps to identify the mechanism of the regional hemlock decline. Here confounding factors are eliminated: tree age distributions are similar, weather patterns are identical, mortality is radically diffeent.

In the study reported here, we followed up on Shannon’s informal observations by measuring hundreds of hemlocks of all sizes, ages, locations and health status over three months, from January through March, 2024. This dataset set the stage for tests of statistical signifcance shown below.

“Graveyard” and “Garden”

These two dense hemlock sites, initially identified by informal inspection, have comparable age distribution - estimated from tree diameter - and contasting health, as these boxplots show. In this analysis, the data are rather crudely separated only on latitude. More nuanced separation appears below.

Subsequent mapping and analysis refined these results - see below.

tbl.graveyard <- subset(tbl, lat >= 47.558934)
tbl.garden    <- subset(tbl, lat <= 47.555554)
boxplot(tbl.graveyard$h, tbl.garden$h, names=c("graveyard", "garden"), main="Hemlock Health scaled 0-3")

boxplot(tbl.graveyard$dbh, tbl.garden$dbh, names=c("graveyard", "garden"),
         main="Hemlock Diameter (DBH inches) a proxy for age")

Students Mapped, Measured and Assessed 600 Hemlock Trees

Between January and March, two Univeristy of Washington students from the Program on the Environment in their senior Capstone Research Project, along with a Garfield High School junior, spent about 200 hours in the forest, collecting data to test the hypothesis that dense hemlock stands

  1. of similar age distrituion
  2. exposed to essentially identical weather patterns
  3. nonethess exhibited sharply contrasting health
  4. thereby complicating popular notions that hemlock decline is due to
    • normal senescence
    • changing weather patterns associated with climate change

Here is a screenshot of the resulting interactive map. The blue circles are hand-drawn visual estimates of the boundaries of the two informally identified contrasting sites. These are replaced below by analytically derived boundaries.

Density Maps: All Hemlocks; dying and dead; healthh hemlocks

Kernel Density solves the “overplotting” problem seen in the map above, in which the overall state of the forest is obscured by the large number of individulally measured and plotted trees. The leftmost plot below shows the density of all hemlocks. The middle shows the density of dead and low health trees. The rightmost plot shows the distribution of healthy hemlocks.

Selecting Contrasting Candidate Sites for Further Study

In the three density maps abovewe have confirmation of our informal observation, that sites of contrasting health are geographically separated.

Out next step is to define two sites of

  1. similar density of hemlocks
  2. contrasting health status
Our method:
  1. subset the full observation table by health
  2. calculate kernel densities of hemlocks in both groups
  3. from these densities, identify the boundaries of comparable sites
library(MASS)
library(RColorBrewer)
options(digits=12)


f <- "https://pshannon.net/hemlockSurvey2024/tblFinal.csv"
tbl <- read.table(f, sep=",", header=TRUE, as.is=TRUE, nrow=-1, quote="")
     # get just the healthy trees
tbl.x <- subset(tbl, h>=2) 
min.density <- 30000
cellCount <- 500
osm.limits <- c(-122.25676, -122.248006, 47.548233, 47.562744) # open street map
limits <- osm.limits

f.healthy <- kde2d(tbl.x$lon, tbl.x$lat, n=cellCount, lims=limits)
z <- f.healthy$z
     # zero out low density cells
z[z <min.density] <- 0
f.healthy$z <- z
     # display if you wish

healthy.colors <- brewer.pal(8, "Greens")
healthy.colors[1] <- "#FFFFFF"
sick.colors <- brewer.pal(8, "Reds")
sick.colors[1] <- "#FFFFFF"

# image(f.healthy, main="healthy", col=healthy.colors) #, zlim = c(0, 0.05))

      # can we get the boundary of the highest density region
      # from the contour?

tbl.x <- subset(tbl, h<=1)
f.sick <- kde2d(tbl.x$lon, tbl.x$lat, n=cellCount, lims=limits)
z <- f.sick$z
z[z <min.density] <- NA
f.sick$z <- z
range(f.sick$z)
## [1] NA NA
#pdf("sick.pdf")
#image(f.sick, main="sick", add=FALSE, col=sick.colors)
boundaries.sick <- contourLines(f.sick)
boundaries.healthy <- contourLines(f.healthy)
print(as.numeric(unlist(lapply(boundaries.sick, "[", "level"))))
##  [1]  40000  50000  60000  60000  70000  80000  90000 100000 110000 120000 130000
print(length(boundaries.sick[[6]]$x))
## [1] 309
print(as.numeric(unlist(lapply(boundaries.healthy, "[", "level"))))
##  [1]  10000  20000  30000  40000  50000  50000  60000  70000  80000  90000 100000 110000 120000
## [14] 130000
print(length(boundaries.healthy[[6]]$x))
## [1] 587
# x <- boundaries.sick[[6]]$x
# y <- boundaries.sick[[6]]$y
# for(i in seq_len(length(x))){
#   print(sprintf("{lat: %12.8f, lng: %12.8f},", y[i], x[i]))
#   }

# x <- boundaries.healthy[[6]]$x
# y <- boundaries.healthy[[6]]$y
# for(i in seq_len(length(x))){
#   print(sprintf("{lat: %12.8f, lng: %12.8f},", y[i], x[i]))
#   }

Density-derived Boundaries for Hemlock Graveyard and Garden